package org.ytor.core.sqlflow.dsl.template;

import org.ytor.core.sqlflow.dsl.expr.ExprAstParser;
import org.ytor.core.sqlflow.dsl.expr.node.ExprNode;
import org.ytor.core.sqlflow.dsl.template.node.TemplateNode;
import org.ytor.core.sqlflow.dsl.template.node.support.BlockNode;
import org.ytor.core.sqlflow.dsl.template.node.support.ForNode;
import org.ytor.core.sqlflow.dsl.template.node.support.IfNode;
import org.ytor.core.sqlflow.dsl.template.node.support.TextNode;
import org.ytor.core.sqlflow.dsl.token.Tokenizer;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * created by yangtong on 2025/8/7 12:03:10
 * <br/>
 * 模板解析器
 */
public class TemplateParser {

    // 4个空格视为一个缩进层级
    private static final int SPACES_PER_INDENT = 4;
    private final List<String> lines;
    private int pos = 0;

    public TemplateParser(String template) {
        // 将模板字符串按行分隔
        this.lines = Arrays.asList(template.replace("\r\n", "\n").split("\n"));
    }

    /**
     * 入口方法：解析整个模板
     */
    public BlockNode parseTemplate() {
        // 以第一行的缩进为初始缩进
        return parseBlock(countIndent(lines.getFirst()));
    }

    /**
     * 递归解析 block（缩进必须匹配 currentIndent）
     */
    private BlockNode parseBlock(int currentIndent) {
        List<TemplateNode> children = new ArrayList<>();

        while (!isAtEnd()) {
            String line = lines.get(pos);
            String content = line.trim();

            // 注释行跳过
            if (content.startsWith("-- ")) {
                pos++;
                continue;
            }

            // 计算当前行的缩进层级
            int indent = countIndent(line);

            if (indent < currentIndent) {
                // 回到上层 block，结束当前解析
                break;
            } else if (indent > currentIndent) {
                throw new RuntimeException("缩进错误：第 " + (pos + 1) + " 行缩进超过预期！");
            }

            // 空行跳过
            if (content.isEmpty()) {
                pos++;
                continue;
            }

            // 解析 if
            if (content.startsWith("if: ")) {
                String exprStr = content.substring(4).trim();
                ExprNode condition = parseExpr(exprStr);
                pos++;
                BlockNode ifBlock = parseBlock(currentIndent + 1);
                children.add(new IfNode(condition, ifBlock));
            }
            // 解析 for
            else if (content.startsWith("for: ")) {
                String var = content.substring(5).trim();
                pos++;
                BlockNode forBlock = parseBlock(currentIndent + 1);
                children.add(new ForNode(var, forBlock));
            }
            // 普通文本
            else {
                // 去除缩进
                //children.add(new TextNode(line.substring(currentIndent)));
                // 保留原始缩进格式
                children.add(new TextNode(line));
                pos++;
            }
        }

        return new BlockNode(children);
    }

    /**
     * 使用已有 Tokenizer + Parser 解析表达式
     */
    private ExprNode parseExpr(String exprStr) {
        Tokenizer tokenizer = new Tokenizer(exprStr);
        ExprAstParser parser = new ExprAstParser(tokenizer.tokenize());
        return parser.parseExpression();
    }

    /**
     * 判断指定行的缩进层级
     */
    private int countIndent(String line) {
        int spaces = 0;
        int tabs = 0;

        for (char c : line.toCharArray()) {
            if (c == ' ') spaces++;
            else if (c == '\t') tabs++;
            else break; // 到第一个非空白字符为止
        }

        // 总缩进等级 = tab数 + 空格数 / 4（向下取整）
        return tabs + (spaces / SPACES_PER_INDENT);
    }

    private boolean isAtEnd() {
        return pos >= lines.size();
    }

}
